RavenDb DeleteByIndex on nested collection condition - ravendb

Assume that I have a schema as below:
Father { // Type: 1
Id
}
Mother { // Type: 2
Id
}
Child {
Parents: [
{ ParentId, ParentType } // ParentType could be 1 or 2 acording to entity's type
]
}
How could I create an index that allow us to DeleteByIndex and accept lucene query such as: "Parents,ParentId:xyz AND Parents,ParentType:2"?
As I tried to create index as below:
Map = views => from view in views
select new
{
view.ParentId,
view.ParentType,
view.Parents
}
RavenDb failed to delete and said that "Parents,ParentId" is not indexed yet.
The reason for doing that is I would like to delete all children data when it is a child of one of {Mother, Father}.

The syntax Parents,ParentId is only applicable for dynamic indexes, using a static index, you are defining the field names, and you can name them however you want.
Map = views => from view in views
from parent in view.Parents
select new
{
parent .ParentId,
parent .ParentType
}
But check the docs about what fanout indexes if your system can have many parents.

Related

Prisma nested recursive relations depth

I must query a group and all of its subgroups from the same model.
However, when fetching from Group table as shown below, Prisma doesn't include more than a 1-depth to the resulting Subgroups relation (subgroups of subgroups being left out). Subgroups attribute holds an array whose elements are of same type as the said model (recursive).
model Group {
id Int #id #default(autoincrement())
parentId Int?
Parent Group? #relation("parentId", fields: [parentId], references: [id])
Subgroups Group[] #relation("parentId")
}
GroupModel.findFirst({
where: { id: _id },
include: { Subgroups: true }
});
I guess this might be some sort of safeguard to avoid infinite recursive models when generating results. Is there any way of dodging this limitation (if it's one), and if so, how?
Thanks
You can query more than 1-depth nested subgroups by nesting include like so:
GroupModel.findFirst({
where: { id: _id },
include: { Subgroups: { include: { Subgroups: { include: Subgroups: { // and so on... } } } } }
});
But, as mentioned by #TasinIshmam, something like includeRecursive is not supported by Prisma at the moment.
The workaround would be to use $queryRaw (https://www.prisma.io/docs/concepts/components/prisma-client/raw-database-access#queryraw) together with SQL recursive queries (https://www.postgresql.org/docs/current/queries-with.html#QUERIES-WITH-RECURSIVE)

Filter Products using Storefront API in shopify

We are developing filters functionality using Storefront API. We can write query with operators as given below to search within parent key such as "product_type" but we couldn't find way to search within child key.
.products(first: 10, query: "tag:blue AND product_type:sneaker") { $0
...
}
So can anyone help us to search within child key's such as variant selected options?
We are expecting query format like:
.products(first: 10, query: "selectedProductVarient.option1:M") { $0
...
}
You can't add a query parameter to a nested connection, but the productVariants() query argument takes all of those filter parameters:
{
productVariants(first: 10, query: "tag:foo product_type:bar option_1:baz") {
nodes {
id
title
product {
productType
tags
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
The option_1 parameter is the name of the option ('size', 'color', etc.), not the value assigned to the variant. You might be better off querying the title.

RavenDB Get document count after BulkInsertOperations

I am using RavenDB to bulk load some documents. Is there a way to get the count of documents loaded into the database?
For insert operations I am doing:
BulkInsertOperation _bulk = docStore.BulkInsert(null,
new BulkInsertOptions{ CheckForUpdates = true});
foreach(MyDocument myDoc in docCollection)
_bulk.Store(myDoc);
_bulk.Dispose();
And right after that I call the following:
session.Query<MyDocument>().Count();
but I always get a number which is less than the count I see in raven studio.
By default, the query you are doing limits to a sane number of results, part of RavenDB's promise to be safe by default and not stream back millions of records.
In order to get the number of a specific type of document in yoru database, you need a special map-reduce index whose job it is to track the counts for each document type. Because this type of index deals directly with document metadata, it's easier to define this in Raven Studio instead of trying to create it with code.
The source for that index is in this question but I'll copy it here:
// Index Name: Raven/DocumentCollections
// Map Query
from doc in docs
let Name = doc["#metadata"]["Raven-Entity-Name"]
where Name != null
select new { Name , Count = 1}
// Reduce Query
from result in results
group result by result.Name into g
select new { Name = g.Key, Count = g.Sum(x=>x.Count) }
Then to access it in your code you would need a class that mimics the structure of the anonymous type created by both the Map and Reduce queries:
public class Collection
{
public string Name { get; set; }
public int Count { get; set; }
}
Then, as Ayende notes in the answer to the previously linked question, you can get results from the index like this:
session.Query<Collection>("Raven/DocumentCollections")
.Where(x => x.Name == "MyDocument")
.FirstOrDefault();
Keep in mind, however, that indexes are updated asynchronously so after bulk-inserting a bunch of documents, the index may be stale. You can force it to wait by adding .Customize(x => x.WaitForNonStaleResults()) right after the .Query(...).
Raven Studio actually gets this data from the index Raven/DocumentsByEntityName which exists for every database, by sidestepping normal queries and getting metadata on the index. You can emulate that like this:
QueryResult result = docStore.DatabaseCommands.Query("Raven/DocumentsByEntityName",
new Raven.Abstractions.Data.IndexQuery
{
Query = "Tag:MyDocument",
PageSize = 0
},
includes: null,
metadataOnly: true);
var totalDocsOfType = result.TotalResults;
That QueryResult contains a lot of useful data:
{
Results: [ ],
Includes: [ ],
IsStale: false,
IndexTimestamp: "2013-11-08T15:51:25.6463491Z",
TotalResults: 3,
SkippedResults: 0,
IndexName: "Raven/DocumentsByEntityName",
IndexEtag: "01000000-0000-0040-0000-00000000000B",
ResultEtag: "BA222B85-627A-FABE-DC7C-3CBC968124DE",
Highlightings: { },
NonAuthoritativeInformation: false,
LastQueryTime: "2014-02-06T18:12:56.1990451Z",
DurationMilliseconds: 1
}
A lot of that is the same data you get on any query if you request statistics, like this:
RavenQueryStatistics stats;
Session.Query<Course>()
.Statistics(out stats)
// Rest of query

PouchDB Query like sql

with CouchDB is possible do queries "like" SQL. http://guide.couchdb.org/draft/cookbook.html says that
How you would do this in SQL:
SELECT field FROM table WHERE value="searchterm"
How you can do this in CouchDB:
Use case: get a result (which can be a record or set of records) associated with a key ("searchterm").
To look something up quickly, regardless of the storage mechanism, an index is needed. An index is a data structure optimized for quick search and retrieval. CouchDB’s map result is stored in such an index, which happens to be a B+ tree.
To look up a value by "searchterm", we need to put all values into the key of a view. All we need is a simple map function:
function(doc) {
if(doc.value) {
emit(doc.value, null);
}
}
This creates a list of documents that have a value field sorted by the data in the value field. To find all the records that match "searchterm", we query the view and specify the search term as a query parameter:
/database/_design/application/_view/viewname?key="searchterm"
how can I do this with PouchDB? the API provide methods to create temp view, but how I can personalize the get request with key="searchterm"?
You just add your attribute settings to the options object:
var searchterm = "boop";
db.query({map: function(doc) {
if(doc.value) {
emit(doc.value, null);
}
}, { key: searchterm }, function(err, res) { ... });
see http://pouchdb.com/api.html#query_database for more info
using regex
import PouchDB from 'pouchdb';
import PouchDBFind from 'pouchdb-find';
...
PouchDB.plugin(PouchDBFind)
const db = new PouchDB(dbName);
db.createIndex({index: {fields: ['description']}})
....
const {docs, warning} = await db.find({selector: { description: { $regex: /OVO/}}})

MongoDB: How retrieve data that is newly constructed instead of original documents in the collection?

I have a collection in which documents are all in this format:
{"user_id": ObjectId, "book_id": ObjectId}
It represents the relationship between user and book, which is also one-to-many, that means, a user can have more than one books.
Now I got three book_id, for example:
["507f191e810c19729de860ea", "507f191e810c19729de345ez", "507f191e810c19729de860efr"]
I want to query out the users who have these three books, because the result I want is not the document in this collection, but a newly constructed array of user_id, it seems complicated and I have no idea about how to make the query, please help me.
NOTE:
The reason why I didn't use the structure like:
{"user_id": ObjectId, "book_ids": [ObjectId, ...]}
is because in my system, books increase frequently and have no limit in amount, in other words, user may read thousands of books, so I think it's better to use the traditional way to store it.
This question is not restricted by MongoDB, you can answer it in relational database thoughts.
Using a regular find you cannot get back all user_id fields who own all the book_id's because you normalized your collection (flattened it).
You can do it, if you use aggregation framework:
db.collection.aggregate([
{
$match: {
book_id: {
$in: ["507f191e810c19729de860ea",
"507f191e810c19729de345ez",
"507f191e810c19729de860efr" ]
}
}
},
{
$group: {
_id: "$user_id",
count: { $sum: 1 }
}
},
{
$match: {
count: 3
}
},
{
$group: {
_id: null,
users: { $addToSet: "$_id" }
}
}
]);
What this does is filters through the pipeline only for documents which match one of the three book_id values, then it groups by user_id and counts how many matches that user got. If they got three they pass to the next pipeline operation which groups them into an array of user_ids. This solution assumes that each 'user_id,book_id' record can only appear once in the original collection.